package com.ruoyi.project.applet.util;
import java.nio.charset.StandardCharsets;
import java.security.*;
import java.security.spec.PKCS8EncodedKeySpec;
import java.util.Base64;
import java.util.UUID;

public class WechatPayAuthUtil {

    /**
     * 生成微信支付V3 Authorization请求头
     * @param method     HTTP方法（GET/POST/PUT等）
     * @param url        请求完整URL（含路径和查询参数）
     * @param body       请求体（GET可为空字符串）
     * @param mchId      商户号
     * @param serialNo   商户API证书序列号
     * @param privateKey 商户私钥（PKCS#8格式）
     * @return Authorization头值
     */
    public static String generateAuthorizationHeader(String method,
                                                     String url,
                                                     String body,
                                                     String mchId,
                                                     String serialNo,
                                                     PrivateKey privateKey) {
        try {
            // 1. 生成签名要素
            String timestamp = String.valueOf(System.currentTimeMillis() / 1000);
            String nonceStr = UUID.randomUUID().toString().replaceAll("-", "");
            String bodyDigest = sha256Hex(body);

            // 2. 构造签名串
            String signatureStr = buildSignatureString(method, url, timestamp, nonceStr, bodyDigest);

            // 3. 生成签名
            String signature = sign(signatureStr.getBytes(StandardCharsets.UTF_8), privateKey);

            // 4. 拼接Authorization头
            return String.format(
                    "WECHATPAY2-SHA256-RSA2048 mchid=\"%s\",nonce_str=\"%s\",timestamp=\"%s\",serial_no=\"%s\",signature=\"%s\"",
                    mchId, nonceStr, timestamp, serialNo, signature);
        } catch (Exception e) {
            throw new RuntimeException("生成Authorization头失败", e);
        }
    }

    /**
     * 构建待签名串
     */
    private static String buildSignatureString(String method,
                                               String url,
                                               String timestamp,
                                               String nonceStr,
                                               String bodyDigest) {
        // URL需要去掉协议和域名，保留路径和查询参数
        String pathAndQuery = url.replaceFirst("^https?://[^/]+", "");

        return String.format("%s\n%s\n%s\n%s\n%s\n",
                method.toUpperCase(),
                pathAndQuery,
                timestamp,
                nonceStr,
                bodyDigest);
    }

    /**
     * SHA256withRSA签名
     */
    private static String sign(byte[] data, PrivateKey privateKey) throws Exception {
        Signature signer = Signature.getInstance("SHA256withRSA");
        signer.initSign(privateKey);
        signer.update(data);
        return Base64.getEncoder().encodeToString(signer.sign());
    }

    /**
     * 计算请求体SHA256摘要（16进制小写）
     */
    private static String sha256Hex(String data) throws NoSuchAlgorithmException {
        if (data == null || data.isEmpty()) {
            return "";
        }
        MessageDigest md = MessageDigest.getInstance("SHA-256");
        byte[] digest = md.digest(data.getBytes(StandardCharsets.UTF_8));
        return bytesToHex(digest);
    }

    /**
     * 字节数组转16进制字符串
     */
    private static String bytesToHex(byte[] bytes) {
        StringBuilder result = new StringBuilder();
        for (byte b : bytes) {
            result.append(String.format("%02x", b));
        }
        return result.toString();
    }

    /**
     * 加载PKCS#8格式私钥
     */
    public static PrivateKey loadPrivateKey(String privateKeyStr) throws GeneralSecurityException {
        privateKeyStr = privateKeyStr.replaceAll("-----\\w+ PRIVATE KEY-----", "")
                .replaceAll("\\s", "");
        byte[] decoded = Base64.getDecoder().decode(privateKeyStr);
        PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(decoded);
        KeyFactory keyFactory = KeyFactory.getInstance("RSA");
        return keyFactory.generatePrivate(keySpec);
    }

    // 使用示例
    public static void main(String[] args) throws Exception {
        // 配置参数（需替换为实际值）
        String method = "POST";
        String url = "https://api.mch.weixin.qq.com/v3/fund-app/mch-transfer/transfer-bills";
        String body = "{\"appid\":\"your_appid\",\"out_bill_no\":\"TX123456789\",...}";
        String mchId = "your_mchid";
        String serialNo = "your_serial_no";
        String privateKeyStr = "-----BEGIN PRIVATE KEY-----\n...\n-----END PRIVATE KEY-----";

        PrivateKey privateKey = loadPrivateKey(privateKeyStr);
        String authHeader = generateAuthorizationHeader(method, url, body, mchId, serialNo, privateKey);

        System.out.println("Authorization: " + authHeader);
    }
}